/*
 * 
 */
package com.oniontech.stamptour.common.database;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Hashtable;

import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;

import com.oniontech.stamptour.common.lang.LOG;
import com.oniontech.stamptour.common.util.FileFilter;
import com.oniontech.stamptour.common.util.StringFilter;

// TODO: Auto-generated Javadoc
/**
 * The Class DatabaseManager.
 * 
 * @author limsy
 * @since 2013/02/04
 */
public class DatabaseManager implements DBContext
{

	/**
	 * 생성자.
	 * 
	 * @author limsy
	 * @since 2013/02/04
	 */
	private DatabaseManager()
	{
		m_bLoaded = false;
		m_DataBaseList = new Hashtable<String, DatabaseHelper>();
	}

	/**
	 * Database를 관리하는 객체의 Instance를 얻는다.
	 * 
	 * @return Database를 관리하는 객체 Instance
	 */
	public static DatabaseManager getInstance()
	{
		if (Instance == null)
		{
			Instance = new DatabaseManager();
		}
		return Instance;
	}

	/**
	 * Asset 폴더의 Database 파일을 복사한다.
	 * 
	 * @param con
	 *            Application Context 객체.
	 */
	public void setDBFileCopy(Context con)
	{
		m_Context = con;
		if (!FileFilter.checkPath(false, DB_PATH))
		{
			try
			{
				FileFilter.copyFromAssetsFolderToSdCard(m_Context.getAssets(),
						"database", DB_PATH);
			} catch (IOException e){
				System.out.println("예외 발생");
			} 
		}

		m_DataBaseCopyInfo = new Hashtable<String, String>();
		String[] path = FileFilter.getFileList(DB_PATH);
		m_DataBaseCopyInfo.put(DB_TYPE_ADDRESS, StringFilter.getSearchTextFromStringArray(path, DB_TYPE_ADDRESS));

		m_bLoaded = true;
	}

	/**
	 * Database를 관리하는 객체를 초기화 한다.<br>
	 * Database 객체를 생성하여 내부에 저장한다.
	 */
	public void initDatabase()
	{
		// SPOT DB SET
		m_DataBaseList.put(DB_TYPE_ADDRESS, new DatabaseHelper(m_Context,
				DB_PATH + m_DataBaseCopyInfo.get(DB_TYPE_ADDRESS)));
	}

	/**
	 * Database객체 초기화 작업이 완료가 되었는지 체크한다.
	 * 
	 * @return 작업완료 여부.
	 */
	public boolean isDBLoaded()
	{
		return m_bLoaded;
	}

	/**
	 * 특정 Database를 Open한다.
	 * 
	 * @param DBId
	 *            Database ID
	 * @param isRead
	 *            읽기 여부.
	 */
	public void openDB(String DBId, boolean isRead)
	{
		if (m_CurrentDB != null && m_CurrentDB.isOpen())
			m_CurrentDB.close();
		/*
		 * 노트에서 오픈시 -jour 이라는 임시 파일이 생기는 문제로 아래로 수정....확인필요
		 */

			m_CurrentDB = isRead ? SQLiteDatabase.openDatabase(DB_PATH
					+ m_DataBaseCopyInfo.get(DBId), null,
					SQLiteDatabase.OPEN_READONLY
							| SQLiteDatabase.NO_LOCALIZED_COLLATORS)
					: SQLiteDatabase.openDatabase(
							DB_PATH + m_DataBaseCopyInfo.get(DBId), null,
							SQLiteDatabase.OPEN_READWRITE
									| SQLiteDatabase.NO_LOCALIZED_COLLATORS);
		
	}

	/**
	 * Open point db.
	 * 
	 * @param DBName
	 *            the dB name
	 * @param isRead
	 *            the is read
	 */
	public void openPointDB(String DBName, boolean isRead)
	{
		if (m_CurrentDB != null && m_CurrentDB.isOpen())
			m_CurrentDB.close();

			m_CurrentDB = isRead ? SQLiteDatabase.openDatabase(
					DB_PATH + DBName, null, SQLiteDatabase.OPEN_READONLY
							| SQLiteDatabase.NO_LOCALIZED_COLLATORS)
					: SQLiteDatabase.openDatabase(DB_PATH + DBName, null,
							SQLiteDatabase.OPEN_READWRITE
									| SQLiteDatabase.NO_LOCALIZED_COLLATORS);
	}

	/**
	 * Open된 Database를 Close한다.
	 */
	public void closeDB()
	{
		m_CurrentDB.close();
	}

	/**
	 * Database를 조회한다.
	 * 
	 * @param query
	 *            조회 정보 객체.
	 * @return 조회 결과 객체.
	 */
	public Cursor DBQuery(DBContentQuery query)
	{
		return m_CurrentDB.query(query.getTableName(), query.getColums(),
				query.getSelection(), query.getSelectionValuse(),
				query.getGroupBy(), query.getHaving(), query.getOrderBy());
	}

	/**
	 * DB query.
	 * 
	 * @param query
	 *            the query
	 * @return the cursor
	 */
	public Cursor DBQuery(String query)
	{
		Cursor c = m_CurrentDB.rawQuery(query, null);

		return c;
	}

	/**
	 * DB insert query.
	 * 
	 * @param query
	 *            the query
	 */
	public void DBInsertQuery(String query)
	{
		m_CurrentDB.execSQL(query);
	}

	/**
	 * Database의 버젼을 얻는다.
	 * 
	 * @param dbId
	 *            Database Id
	 * @return 버젼정보.
	 */
	public String getDBVersion(String dbId)
	{
		String version = m_DataBaseCopyInfo.get(dbId);
		if (version != null)
		{
			int end = version.length() - 3;
			return version.substring(end - 4, end);
		} else
		{
			return "0001";
		}
	}

	/**
	 * 새로운 버젼의 Database를 복사한다.
	 * 
	 * @param dbType
	 *            복사할 Database Id
	 * @param newFileName
	 *            복사할 파일 이름.
	 * @param input
	 *            복사할 파일 InputStream객체.
	 * @throws FileNotFoundException
	 *             the file not found exception
	 * @throws IOException
	 *             Signals that an I/O exception has occurred.
	 */
	public void updateDatabaseFile(String dbType, String newFileName,
			byte[] input) throws FileNotFoundException, IOException
	{
		boolean flag = FileFilter.fileDelete(DB_PATH
				+ m_DataBaseCopyInfo.remove(dbType));
		LOG.Log_DEV(TAG, "File Delete ? " + flag);
		FileFilter.copyFromNetworkFileToSdCard(input, DB_PATH, newFileName);
		m_DataBaseCopyInfo.put(dbType, newFileName);
	}

	/**
	 * Database 관리 객체의 메모리를 환원한다.
	 */
	public void destory()
	{
		if (m_CurrentDB != null && m_CurrentDB.isOpen())
			m_CurrentDB.close();

		if (m_DataBaseList != null)
		{
			m_DataBaseList.clear();
			m_DataBaseList = null;
		}

		if (m_DataBaseCopyInfo != null)
		{
			m_DataBaseCopyInfo.clear();
			m_DataBaseCopyInfo = null;
		}

		m_Context = null;
		Instance = null;
	}

	/** LOG에 쓰일 Tag 변수. */
	private static final String TAG = DatabaseManager.class.getSimpleName();

	/** Database 관리 객체의 Instance 변수. */
	private static DatabaseManager Instance = null;

	/** Application Context 객체 변수. */
	private Context m_Context;

	/** Database저장 및 관리 객체 변수. */
	private Hashtable<String, DatabaseHelper> m_DataBaseList = null;

	/** Database 파일 저장 관련 객체 변수. */
	private Hashtable<String, String> m_DataBaseCopyInfo = null;

	/** 현제 열린 Database객체를 저장할 변수. */
	private SQLiteDatabase m_CurrentDB;

	/** 객체 초기화 작업 완료여부 변수. */
	private boolean m_bLoaded;
}

final class DatabaseHelper extends SQLiteOpenHelper
{

	public DatabaseHelper(Context context, String name)
	{
		super(context, name, null, 1);
		int end = name.length() - 3;
		m_strDBVersion = name.substring(end - 4, end);
		LOG.Log_DEV("DatabaseHelper", "name : " + name + " Version : "
				+ m_strDBVersion);
	}

	@Override
	public void onCreate(SQLiteDatabase db)
	{
	}

	@Override
	public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)
	{
	}

	private String m_strDBVersion;
}
